package com.zshan.clinic.mini.interceptor;


import com.zshan.clinic.common.constant.HeaderConstant;
import com.zshan.clinic.common.entity.HeaderDTO;
import com.zshan.clinic.common.enums.ResultEnum;
import com.zshan.clinic.common.response.RestResp;
import com.zshan.clinic.common.util.json.JsonUtil;
import com.zshan.clinic.common.util.redis.RedisUtil;
import com.zshan.clinic.common.util.string.StringUtil;
import com.zshan.clinic.mini.annotation.Permission;
import com.zshan.clinic.mini.constant.MiniConstant;
import com.zshan.clinic.mini.constant.MiniRedisKeyPrefix;
import com.zshan.clinic.mini.entity.UserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 登录拦截
 * @author lichen
 */
@Component
@Slf4j
public class SessionCheckInterceptor implements HandlerInterceptor {


	@Autowired
	private RedisUtil redisUtil;


	/**
	 * 获取公共参数
	 */
	public HeaderDTO getHeader(HttpServletRequest request) {
		HeaderDTO headerDTO = new HeaderDTO();
		headerDTO.setIp(request.getHeader(HeaderConstant.IP));
		headerDTO.setToken(request.getHeader(HeaderConstant.TOKEN));
		String clinicId = request.getHeader(HeaderConstant.CLINIC_ID);
		if(StringUtil.isNotBlank(clinicId)){
			headerDTO.setClinicId(Long.parseLong(clinicId));
		}
		return headerDTO;
	}

	/**
	 * 登录权限验证
	 * 方法拦截 Controller 处理之前进行调用
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		String requestUri = request.getRequestURI();
		HeaderDTO headerDTO = getHeader(request);
		log.info("请求地址：{},header参数:{}",requestUri,headerDTO);
		//白名单验证
		if(MiniConstant.isInterceptorAllow(requestUri)){
			return true;
		}
		//参数验证
		Long clinicId = headerDTO.getClinicId();
		if(StringUtil.isBlank(clinicId)){
			//header中没有诊所ID
			return failHandle(response,RestResp.FAIL(ResultEnum.UN_AUTHORIZED.getValue(), ResultEnum.UN_AUTHORIZED.getText()));
		}
		HandlerMethod handlerMethod = null;
		try{
			handlerMethod = (HandlerMethod)handler;
		} catch (Exception e){
			return failHandle(response, RestResp.SYSTEM_FAIL("请求地址错误"));
		}
		Method method = handlerMethod.getMethod();
		//登录验证
		Permission permission = method.getAnnotation(Permission.class);
		if(permission != null){
			//不需要登录的接口
			return true;
		}
		UserInfo userInfo = getUserInfo(headerDTO.getToken());
		if(userInfo == null){
			//如果用户没有登录并且接口也没有permission注解，说明接口需要登录
			return failHandle(response,RestResp.FAIL(ResultEnum.UN_LOGIN.getValue(), ResultEnum.UN_LOGIN.getText()));
		}
		return true;
	}

	public UserInfo getUserInfo(String token){
		if(StringUtil.isBlank(token)){
			return null;
		}
		return (UserInfo) redisUtil.get(String.format(MiniRedisKeyPrefix.USER_TOKEN,token));
	}

	private boolean failHandle(HttpServletResponse response,RestResp restResp) throws Exception {
		response.setStatus(200);
		response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
		response.getWriter().write(JsonUtil.obj2Json(restResp));
		return false;
	}
}
